#include			"TcpServer.h"

TcpServer::TcpServer(Async & async, PacketHandler * handler) : _acceptor(async.getService(), boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 4242)), _handler(handler), _current_id(1)
{

}

TcpServer::~TcpServer()
{

}

void				TcpServer::start()
{
	std::cout << "[INFO] Started TCP server on port " << _acceptor.local_endpoint().port() << std::endl;
	_start_accept();
}

void				TcpServer::_start_accept()
{
	TcpSocket::SocketPtr		socket;

	socket = TcpSocket::create(_acceptor.get_io_service(), _current_id);
	_acceptor.async_accept(socket->getSocket(), boost::bind(&TcpServer::_handle_accept, this, socket, boost::asio::placeholders::error));
}

void				TcpServer::_handle_accept(TcpSocket::SocketPtr socket, const boost::system::error_code & error)
{
	std::cout << "[INFO] New TCP client ip=[" << socket->getSocket().remote_endpoint().address().to_string() << "] " << std::endl;
	if (!error)
	{
		socket->setHandler(_handler);
		_sockets[_current_id] = socket;
		_current_id++;
		socket->start();
	}
	_start_accept();
}

void				TcpServer::sendPacket(Packet *packet , unsigned int id)
{
	if (_sockets.find(id) != _sockets.end())
		_sockets[id]->write(packet->toTcpNetworkPacket(), packet->size() + sizeof(unsigned short));
	else
		std::cout << "[CRITICAL] socket id " << id << " was not found" << std::endl;
}

unsigned int		TcpServer::getId(std::string ip)
{
  for (std::map<unsigned int, TcpSocket::SocketPtr>::iterator it = _sockets.begin(); it != _sockets.end(); ++it)
    {
      if ((*it).second->getIp() == ip)
	return (*it).second->getId();
    }
  return 0;
}

std::string			TcpServer::getIp(unsigned int id)
{
	if (isOpen(id))
		return _sockets[id]->getIp();
	else 
		std::cout << "[ERROR] Can't find socket id " << id << std::endl;
	return std::string();
}

bool				TcpServer::isOpen(unsigned int id)
{
	return _sockets.find(id) != _sockets.end();
}

void				TcpServer::closeSocket(unsigned int id)
{
	if (isOpen(id))
	{
	  std::cout << "[INFO] Session closed." << std::endl;
		_sockets.erase(id);
	}
}
